/**
 * 
 */
package at.fhooe.mcm12.java.clients;

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.rmi.RemoteException;
import java.util.ArrayList;
import java.util.Vector;

import javax.swing.Box;
import javax.swing.DefaultListModel;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.ListSelectionModel;
import javax.swing.SwingUtilities;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;

import at.fhooe.mcm12.java.GUIElements.TextPanel;
import at.fhooe.mcm12.java.interfaces.RMISensorInterface;
import at.fhooe.mcm12.java.sensors.data.SensorValue;
import at.fhooe.mcm12.java.utils.TimeUtils;

/**
 * @author Lisi
 * 
 */
public class GUIClient extends AbstractClient implements ActionListener,
		ListSelectionListener {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	private ArrayList<RMISensorInterface> m_allAvailableSensors;
	private static ArrayList<RMISensorInterface> m_registeredSensors;

	// GUI
	private JFrame m_frame;
	private Vector<JCheckBox> m_sensorCheckBoxes;
	private static TextPanel m_textPanel;

	private static JList m_list;
	private static DefaultListModel m_listModel;

	/**
	 * Constructor
	 */
	public GUIClient() {
		super();
		try {
			m_allAvailableSensors = m_clientManager.getSensors();
			m_clientManager.enable(this);
		} catch (RemoteException e) {
			e.printStackTrace();
		}
		m_registeredSensors = new ArrayList<>();
		this.initGUI();
	}

	@SuppressWarnings("unchecked")
	private void initGUI() {
		// GUI
		m_frame = new JFrame("GUIClient");
		m_frame.setSize(500, 500);
		m_frame.setLayout(new BorderLayout());
		m_frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

		// ------ Sensor List and TextPanel-----
		m_textPanel = new TextPanel("", "");
		m_listModel = new DefaultListModel();
		m_list = new JList(m_listModel);
		m_list.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION);
		m_list.setLayoutOrientation(JList.VERTICAL_WRAP);
		m_list.setVisibleRowCount(-1);
		m_list.addListSelectionListener(this);

		m_sensorCheckBoxes = new Vector<JCheckBox>();

		if (m_allAvailableSensors != null && m_allAvailableSensors.size() > 0) {

			// generate Checkboxes for each sensor
			for (RMISensorInterface abstractSensor : m_allAvailableSensors) {

				JCheckBox jb = null;
				try {
					jb = new JCheckBox(abstractSensor.getName());
					jb.addActionListener(this);
					m_sensorCheckBoxes.add(jb);
				} catch (RemoteException e) {
					e.printStackTrace();
				}

			}

			// add all checkboxes to a box
			Box verticalBox = Box.createHorizontalBox();
			for (JCheckBox cb : m_sensorCheckBoxes) {
				verticalBox.add(cb);
			}

			// add elements to frame
			m_frame.add(verticalBox, BorderLayout.NORTH);
			m_frame.add(m_list, BorderLayout.WEST);
			m_frame.add(m_textPanel, BorderLayout.CENTER);

		} else {
			System.out.println("sensorList is null or has no entries");

			// testing GUI Elements
			// //checkboxes
			// JCheckBox jb1 = new JCheckBox("jb1");
			// m_sensorCheckBoxes.add(jb1);
			// JCheckBox jb2 = new JCheckBox("jb2");
			// m_sensorCheckBoxes.add(jb2);
			// JCheckBox jb3 = new JCheckBox("jb3");
			// m_sensorCheckBoxes.add(jb3);
			//
			// // add all checkboxes to a box
			// Box verticalBox = Box.createHorizontalBox();
			// for (JCheckBox cb : m_sensorCheckBoxes) {
			// verticalBox.add(cb);
			// }
			//
			// //list items
			// m_listModel.addElement("item");
			// m_listModel.addElement("item");
			// m_listModel.addElement("item");
			// m_listModel.addElement("item");
			//
			// //text panel
			// m_textPanel.setTitle("Test-Title");
			// m_textPanel.getTextArea().setText("test \n test \n looooooooooooooooooooooooooooooooooooong test \n test");
			//
			// // add elements to frame
			// m_frame.add(verticalBox, BorderLayout.NORTH);
			// m_frame.add(m_list, BorderLayout.WEST);
			// m_frame.add(m_textPanel, BorderLayout.CENTER);

		}

		// set everything visible
		m_frame.setVisible(true);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * at.fhooe.mcm12.java.interfaces.ISensorListener#onSensorValueReceived(
	 * at.fhooe.mcm12.java.sensors.AbstractSensor,
	 * at.fhooe.mcm12.java.sensors.data.SensorValue)
	 */
	@Override
	public void onSensorValueReceived(final String sensorName, final SensorValue value) {
		updateSensorInfo();
		System.out.println("GUI-Client: Sensor: " + sensorName + "Value: "+ value.toString());
	}

	/**
	 * Sets the sensor info to textpanel
	 * 
	 * @param _sensor
	 *            which info should be displayed
	 * @throws RemoteException
	 */
	private void setSensorInfo(RMISensorInterface _sensor)
			throws RemoteException {
		if (_sensor == null)
			return;

		// is selected in list - set the textpanel
		m_textPanel.setTitle(_sensor.getName());

		StringBuffer sb = new StringBuffer();
		sb.append("Description: ");
		sb.append(_sensor.getDescription());
		sb.append("\n");

		sb.append("Value: ");
		sb.append(_sensor.getDataType().toString());
		sb.append("\n");

		sb.append("Timestamp: ");
		sb.append(TimeUtils.getCurrentTimeStamp(_sensor.getDataType()
				.getTimestamp()));
		sb.append("\n");

		sb.append("SensorTpe: ");
		sb.append(_sensor.getSensorType().toString());
		sb.append("\n");

		m_textPanel.getTextArea().setText(sb.toString());
	}

	private void updateSensorInfo() {
		if(m_list == null){
			m_list = new JList();
		}
		
		if (m_list.getSelectedIndex() >= 0) {
			String sensorName = (String) m_listModel.getElementAt(m_list
					.getSelectedIndex());
			for (RMISensorInterface sensorInterface : m_registeredSensors) {
				try {
					if (sensorInterface.getName().equals(sensorName)) {
						if (sensorInterface.isActive())
							setSensorInfo(sensorInterface);
						return;
					}
				} catch (RemoteException e) {
					e.printStackTrace();
				}
			}
		}
	}

	@SuppressWarnings("unchecked")
	@Override
	public void actionPerformed(ActionEvent e) {

		// check if a checkbox was checked
		if (e.getSource() instanceof JCheckBox) {

			// check which checkbox was checked
			JCheckBox curCheckbox;
			for (int i = 0; i < m_sensorCheckBoxes.size(); i++) {
				curCheckbox = m_sensorCheckBoxes.elementAt(i);
				if (e.getSource().equals(curCheckbox)) {
					if (!curCheckbox.isSelected()) {
						// unregister and remove from list
						try {
							m_clientManager.unregisterFor(this,
									m_allAvailableSensors.get(i));
							System.out.println("unregisterd sensor: "
									+ m_allAvailableSensors.get(i).getName());
						} catch (RemoteException e1) {
							e1.printStackTrace();
						}
						// remove from vector and list
						int sensorIndex = m_registeredSensors
								.indexOf(m_allAvailableSensors.get(i));

						boolean flag = false;
						if (m_list.getSelectedIndex() == sensorIndex) {
							flag = true;
						}

						m_listModel.remove(sensorIndex);
						m_registeredSensors.remove(sensorIndex);

						if (m_registeredSensors.size() == 0)
							m_textPanel.getTextArea().setText("");
						else if (flag) {
							m_list.setSelectedIndex(0);
						}
						updateSensorInfo();

					} else {
						// register and add to list
						try {
							m_clientManager.registerFor(this,
									m_allAvailableSensors.get(i));
							System.out.println("registerd sensor: "
									+ m_allAvailableSensors.get(i).getName());

							// add to vector and list
							m_registeredSensors.add(m_allAvailableSensors
									.get(i));
							m_listModel.add(m_registeredSensors.size() - 1,
									m_allAvailableSensors.get(i).getName());

							if (m_registeredSensors.size() == 1) {
								m_list.setSelectedIndex(0);
							}

						} catch (RemoteException e1) {
							e1.printStackTrace();
						}

					}
				}
			}
		}
	}

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		@SuppressWarnings("unused")
		GUIClient guiClient = new GUIClient();

	}

	@Override
	public String getName() {
		return "GUI Client";
	}

	@Override
	public void valueChanged(ListSelectionEvent e) {
		// value in selection list has changed - change sensor info
		int index = m_list.getSelectedIndex();
		try {
			if (index < 0)
				index = 0;
			if (m_list.getModel().getSize() != 0)
				this.setSensorInfo(m_registeredSensors.get(index));
		} catch (RemoteException e1) {
			e1.printStackTrace();
		}
	}
}
